package com.baturu.vin.benz.service.impl.supers;

import com.baturu.vin.benz.consts.BenzConstant;
import com.baturu.vin.benz.dal.dao.BenzFootnoteDAO;
import com.baturu.vin.benz.dto.*;
import com.baturu.vin.benz.dto.footnote.Footnote;
import com.baturu.vin.benz.dto.footnote.FootnoteList;
import com.baturu.vin.benz.dto.footnote.FootnoteRev9Color;
import com.baturu.vin.benz.dto.footnote.PartInfo;
import com.baturu.vin.benz.service.impl.BenzCarTypeInfoService;
import com.baturu.vin.benz.service.impl.BenzFootnotesService;
import com.baturu.vin.benz.service.impl.BenzSpringService;
import com.baturu.vin.benz.service.impl.util.BenzI18nService;
import com.baturu.vin.benz.service.impl.util.BenzStringUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * BenzSuperPartsFilterService
 *
 * @author majianming
 * @date 2019-04-19 17:51
 */
@Service
public class BenzSuperPartsFilterService {

    @Autowired
    private BenzFootnoteDAO footnoteDAO;
    @Autowired
    private BenzFootnoteDAO benzFootnoteDAO;

    @Autowired
    private BenzFootnotesService benzFootnotesService;
    @Autowired
    private BenzCarTypeInfoService benzCarTypeInfoService;
    @Autowired
    private BenzSpringService benzSpringService;

    @Autowired
    private BenzI18nService benzI18nService;

    public static Map<String, List<BenzSuperPartsInfoDTO>> getPartsByCallout(List<BenzSuperPartsInfoDTO> epcPartsInfos) {
        Map<String, List<BenzSuperPartsInfoDTO>> partByCalloutHash = Maps.newHashMap();
        for (BenzSuperPartsInfoDTO epcPartsInfo : epcPartsInfos) {
            addPartToMap(partByCalloutHash, epcPartsInfo);
        }
        return partByCalloutHash;
    }


    /**
     * 通过车型过滤
     *
     * @return 如果符合车型 那么返回<code>true</code>，否则返回<code>false</code>
     */
    private boolean filterByModel(BenzSuperPartsInfoDTO partsInfoDTO, Set<BenzPartCatInfoDTO> modelInfos) {
        if (Objects.isNull(partsInfoDTO)) {
            return false;
        }
        String partMdl = partsInfoDTO.getType();
        String partSubMod = partsInfoDTO.getSubMods();
        if (StringUtils.isBlank(partSubMod)) {
            return true;
        }

        return modelInfos.stream().anyMatch(modelInfo -> {
            String mdlType = "";
            String mdlSubbm1 = "";
            String mdlSubbm2 = "";
            String catType2 = "";
            String subbm = null;
            if (Objects.nonNull(modelInfo)) {
                mdlType = modelInfo.getType();
                mdlSubbm1 = modelInfo.getSubbm1();
                mdlSubbm2 = modelInfo.getSubbm2();
                catType2 = modelInfo.getCatTyp2();
            }
            if (partMdl.trim().equals(mdlType)) {
                if (catType2 != null && catType2.trim().equals("9")) {
                    subbm = mdlSubbm2;
                } else {
                    subbm = mdlSubbm1;
                }
                for (int i = 0; i < partSubMod.length(); i += 3) {
                    if (subbm != null && subbm.equals(partSubMod.substring(i, i + 3))) {
                        return true;
                    }
                }
            }
            return false;
        });


    }

    /**
     * 通过变速箱信息过滤
     *
     * @param partsInfoDTO
     * @param transmissionInfo
     * @param chassIdent
     * @return
     */
    private boolean filterBySteerTrans(BenzSuperPartsInfoDTO partsInfoDTO, BenzPartCatInfoDTO transmissionInfo, String chassIdent) {
        if (transmissionInfo == null) {
            return true;
        }
        String vehSteering = " ";
        String substring = chassIdent.substring(0, 1);
        if ("1".equals(substring) || "5".equals(substring)) {
            vehSteering = "L";
        }
        if ("2".equals(substring) || "6".equals(substring)) {
            vehSteering = "R";
        }

        if (" ".equals(vehSteering)) {
            return true;
        }
        String classNo = transmissionInfo.getClassNo();
        String transType = transmissionInfo.getAggType();
        boolean auto = false;
        boolean manual = false;
        if (StringUtils.isNotBlank(transType) && "GA".equals(transType)) {
            auto = true;
        }
        if (StringUtils.isNotBlank(transType) && "GM".equals(transType)) {
            manual = true;
        }
        String partSteer = partsInfoDTO.getSteering();
        if (StringUtils.isBlank(partSteer)) {
            partSteer = "";
        }
        if (partSteer.length() < 4) {
            int padding = 4 - partSteer.length();
            for (int i = 0; i < padding; i++) {
                partSteer += " ";
            }
        }
        if ("1".equals(classNo) || "2".equals(classNo) || "3".equals(classNo)) {
            switch (partSteer) {
                case "    ":
                    return true;
                case "X   ":
                    return !("R".equals(vehSteering) || auto);
                case " X  ":
                    return !("R".equals(vehSteering) || manual);
                case "  X ":
                    return !("L".equals(vehSteering) || auto);
                case "   X":
                    return !("L".equals(vehSteering) || manual);
                case "X X ":
                    return !auto;
                case " X X":
                    return !manual;
                case "XX  ":
                    return !"R".equals(vehSteering);
                case "  XX":
                    return !"L".equals(vehSteering);
                case "X  X":
                    return !("L".equals(vehSteering) && auto || "R".equals(vehSteering) && manual);
                case " XX ":
                    return !("L".equals(vehSteering) && manual || "R".equals(vehSteering) && auto);
                case "XXX ":
                    return !("R".equals(vehSteering) && auto);
                case " XXX":
                    return !("L".equals(vehSteering) && manual);
                case "XX X":
                    return !("R".equals(vehSteering) && manual);
                case "X XX":
                    return !("L".equals(vehSteering) && auto);
                default:
                    return true;
            }
        }
        String version = partsInfoDTO.getSteering();
        if (partSteer.charAt(0) == 'X' || partSteer.charAt(1) == 'X') {
            return !("R".equals(version) || "R".equals(vehSteering));
        } else if ((partSteer.charAt(2) == 'X' || partSteer.charAt(3) == 'X')) {
            return !("L".equals(version) || "L".equals(vehSteering));
        }
        return true;

    }

    private boolean filterByFootNote(BenzSuperPartsInfoDTO partsInfoDTO,
                                     List<BenzFootnoteDTO> benzFootnoteDTOS,
                                     BenzPartCatInfoDTO chass,
                                     BenzVinInfoDTO benzVinInfoDTO,
                                     String plants) {

        if (Objects.isNull(partsInfoDTO)) {
            return false;
        }
        if (CollectionUtils.isEmpty(benzFootnoteDTOS)) {
            return true;
        }
        String source = chass.getSource();
        FootnoteList fn = benzFootnotesService.getFootnoteList(source, plants, benzFootnoteDTOS);
        FootnoteList filteredFootNotes = benzFootnotesService.filterFootNoteList(fn, fn, benzVinInfoDTO, chass);
        PartInfo partInfo = new PartInfo(fn, filteredFootNotes);
        return validatePartByFootnote(partsInfoDTO, benzVinInfoDTO, partInfo, chass);
    }

    private boolean validatePartByFootnote(BenzSuperPartsInfoDTO p, BenzVinInfoDTO benzVinInfoDTO, PartInfo pInfo, BenzPartCatInfoDTO chass) {
        if (p == null) {
            return true;
        }

        if (StringUtils.isBlank(p.getFootnotes())) {
            return true;
        }
        FootnoteList footnotes = pInfo.getFilteredFootnotes();
        if (footnotes.size() == 0) {
            return true;
        }
        FootnoteList fnl = footnotes.getFootnotes(p.getFootnotes());
        if (fnl.size() == 0) {
            return true;
        }
        FootnoteList fnlSerial = fnl.getSerialFootnotes();
        boolean rV = true;
        if (fnlSerial != null && fnlSerial.size() != 0) {
            int partFootnoteStatus = -1;
            for (int x = 0; x < fnlSerial.size(); ++x) {
                Footnote currentFootnote = fnlSerial.get(x);
                int validStatus = currentFootnote.getValidStatus();
                if (validStatus == 0 || validStatus == 1) {
                    rV = validStatus == 0;
                    partFootnoteStatus = validStatus;
                    break;
                }
                if (validStatus == 8) {
                    partFootnoteStatus = validStatus;
                    continue;
                }
                if (partFootnoteStatus != 8) {
                    if (partFootnoteStatus != 7 && partFootnoteStatus != 6) {
                        partFootnoteStatus = validStatus;
                        continue;
                    }
                    if (validStatus == 6) {
                        partFootnoteStatus = validStatus;
                        continue;
                    }
                    if (validStatus == 7 && partFootnoteStatus != 6) {
                        partFootnoteStatus = validStatus;
                    }
                }
            }
            if (rV && partFootnoteStatus >= 3 && partFootnoteStatus <= 6) {
                rV = false;
            }
        }
        if (rV) {
            FootnoteList filteredfnl = benzFootnotesService.filterFootNoteList(fnl, footnotes, benzVinInfoDTO, chass);
            if (filteredfnl.size() <= 0) {
                rV = true;
            } else {
                FootnoteList colorfnl = filteredfnl.getFootnotesByType(FootnoteRev9Color.class);
                if (filteredfnl.nonUniqueES2(colorfnl)) {
                    p.setEs2Code(colorfnl.get(0).getEs2Codes());
                }
                rV = true;
            }
        }
        FootnoteList filteredFootnotes = pInfo.getFilteredFootnotes();
        benzFootnotesService.footnoteColorFiltering(p, chass, filteredFootnotes);
        benzFootnotesService.partsColorFiltering(p, filteredFootnotes);
        return rV;
    }

    private static void addPartToMap(Map<String, List<BenzSuperPartsInfoDTO>> partByCalloutHash, BenzSuperPartsInfoDTO epcPartsInfo) {
        String posAddress = epcPartsInfo.getPositionAddress();
        String callout = epcPartsInfo.getCallout();
        String hashKey = callout + "_" + posAddress;
        if (StringUtils.isBlank(callout) || callout.equals("-----")) {
            return;
        }
        if (partByCalloutHash.containsKey(hashKey)) {
            List<BenzSuperPartsInfoDTO> partsWithSameCallout = partByCalloutHash.get(hashKey);
            partsWithSameCallout.add(epcPartsInfo);
        } else {
            List<BenzSuperPartsInfoDTO> partsWithSameCallout = Lists.newArrayList();
            partsWithSameCallout.add(epcPartsInfo);
            partByCalloutHash.put(hashKey, partsWithSameCallout);
        }
    }

    /**
     * 过滤配件信息
     *
     * @param benzSuperPartsInfoDTOS 未过滤的配件信息
     * @param baseCodes
     * @return 通过车型过滤后的配件信息
     */
    public List<BenzSuperPartsInfoDTO> filterParts(Collection<BenzSuperPartsInfoDTO> benzSuperPartsInfoDTOS, BenzSuperCarInfoDTO superCarInfoDTO, Collection<String> baseCodes) {
        if (CollectionUtils.isEmpty(benzSuperPartsInfoDTOS) || CollectionUtils.isEmpty(baseCodes)) {
            return Collections.emptyList();
        }
        List<Map<String, String>> plantsCodesMap = benzFootnoteDAO.getPlantsCodes();
        Map<String, String> plantsCodes = Maps.newHashMap(
                plantsCodesMap.stream()
                        .collect(Collectors.toMap(k -> k.get("whc"), k -> k.get("plants"), (k1, k2) -> k1)));
        BenzSuperPartsInfoDTO benzSuperPartsInfoDTO = benzSuperPartsInfoDTOS.stream().findFirst().get();
        String plants = plantsCodes.get(superCarInfoDTO.getWhc());
        String group = benzSuperPartsInfoDTO.getGroup();
        String landCode = benzI18nService.getBenzLangEnum().getLandCode();
        BenzSuperCarConfigurationDTO benzSuperCarConfigurationDTO = superCarInfoDTO.getBenzSuperCarConfigurationDTO();
        List<BenzFootnoteDTO> benzFootnoteDTOS = footnoteDAO.queryFootNoteByCarInfo(benzSuperPartsInfoDTO.getCatNum(), group, landCode);

        Set<BenzPartCatInfoDTO> modelInfos = Sets.newHashSet();
        BenzPartCatInfoDTO engineInfo = benzSuperCarConfigurationDTO.getCatInfoMap().get(BenzConstant.ENGINE_INFO_KEY);
        BenzPartCatInfoDTO chass = benzSuperCarConfigurationDTO.getCatInfoMap().get(BenzConstant.CHASS_INFO_KEY);
        BenzPartCatInfoDTO transmissionInfo = benzSuperCarConfigurationDTO.getCatInfoMap().get(BenzConstant.TRANSMISSION_INFO_KEY);
        baseCodes.forEach(baseCode -> {
            if (StringUtils.isBlank(baseCode)) {
                return;
            }
            BenzPartCatInfoDTO modelInfo;
            if (StringUtils.equals(baseCode, benzSuperCarConfigurationDTO.getEngineNo())) {

                modelInfo = engineInfo;
            } else if (StringUtils.equals(baseCode, benzSuperCarConfigurationDTO.getCarNo())) {

                modelInfo = chass;
            } else if (StringUtils.equals(baseCode, benzSuperCarConfigurationDTO.getTransmissionNo())) {

                modelInfo = transmissionInfo;
            } else {
                modelInfo = chass;
            }
            modelInfos.add(modelInfo);
        });

        Set<String> saCodeSet = benzSuperCarConfigurationDTO.getBenzSaDescDTOS().stream().map(BenzSaDescDTO::getSaCode).collect(Collectors.toSet());
        BenzVinInfoDTO benzVinInfoDTO = benzSuperCarConfigurationDTO.getBenzVinInfoDTO();
        String chassIdent = superCarInfoDTO.getChassIdent();
        List<BenzSuperPartsInfoDTO> collect = benzSuperPartsInfoDTOS.stream().filter(p ->
                filterByModel(p, modelInfos)
                        && filterBySteerTrans(p, transmissionInfo, chassIdent)
                        && BenzStringUtil.filterBySaCode(p, saCodeSet, chass)
                        && filterByFootNote(p, benzFootnoteDTOS, chass, benzVinInfoDTO, plants)
                        && filterPartsBySprings(p, benzVinInfoDTO)
        ).collect(Collectors.toList());
        return filterCodeEvaluation(collect, chass, saCodeSet);
    }

    private List<BenzSuperPartsInfoDTO> filterCodeEvaluation(List<BenzSuperPartsInfoDTO> partsInfos, BenzPartCatInfoDTO modelInfo, Set<String> saCodeSet) {
        String source = modelInfo.getSource();
        if (CollectionUtils.isEmpty(partsInfos) || StringUtils.isBlank(source) || !(source.equals("D") || source.equals("M"))) {
            return partsInfos;
        }
        List<BenzSuperPartsInfoDTO> partsToRemove = Lists.newArrayList();
        Map<String, List<BenzSuperPartsInfoDTO>> partsByCalloutPosAddrHash = getPartsByCallout(partsInfos);
        if (partsByCalloutPosAddrHash.isEmpty()) {
            return partsInfos;
        }
        Set<String> e = partsByCalloutPosAddrHash.keySet();
        for (String calloutPosAddr : e) {
            List<BenzSuperPartsInfoDTO> partsWithSameCalloutPosAddr = partsByCalloutPosAddrHash.get(calloutPosAddr);
            int highScore = 0;
            if (CollectionUtils.isEmpty(partsWithSameCalloutPosAddr)) {
                continue;
            }
            for (BenzSuperPartsInfoDTO p : partsWithSameCalloutPosAddr) {
                if (p.isAccessoryPart() || StringUtils.isBlank(p.getSaCode()) || p.getSaCode().trim().length() == 0) {
                    continue;
                }
                int score = BenzStringUtil.scoreCodeBString(p.getSaCode(), saCodeSet);
                p.setCodeBScore(score);
                if (score > highScore) {
                    highScore = score;
                }
            }
            for (BenzSuperPartsInfoDTO p : partsWithSameCalloutPosAddr) {
                if (p.isAccessoryPart()) {
                    continue;
                }
                if (p.getCodeBScore() < highScore) {
                    partsToRemove.add(p);
                }
            }
        }
        partsInfos.removeAll(partsToRemove);
        return partsInfos;
    }

    /**
     * 弹簧过滤
     *
     * @param partsInfo
     * @param benzVinInfoDTO
     * @return
     */
    private boolean filterPartsBySprings(BenzEPCPartsInfoDTO partsInfo, BenzVinInfoDTO benzVinInfoDTO) {
        if (Objects.isNull(partsInfo)) {
            return false;
        }
//    只有32的这个组才使用弹簧过滤
        if (!StringUtils.equals(partsInfo.getGroupNum(), "32")) {
            return true;
        }
        BenzSpring benzSpring = benzCarTypeInfoService.getBenzSpring(benzVinInfoDTO.getWhc(), benzVinInfoDTO.getChassbm(), benzVinInfoDTO.getChassIdent());
        if (Objects.isNull(benzSpring)) {
            return true;
        }
        List<BenzEPCPartsInfoDTO> benzEPCPartsInfoDTOS = benzSpringService.validateSpring(Lists.newArrayList(partsInfo), benzSpring);
        return CollectionUtils.isNotEmpty(benzEPCPartsInfoDTOS);
    }
}
